/******************************************************************************
*  Copyright(c) 2021-2023 Sietium
*
*  @file:    Node.cpp
*  @brif:    uniform interface
*
*  @date:    05/10/2021
*  @Author:  cary.Zhang
*  @details:
*
******************************************************************************/
#include "textrender.h"
#include "node.h"

Node::Node()
{
    averageFps = 0.0;
}

Node::NodeType Node::getNodeType()
{
    return NodeType_Generic;
}

std::string Node::getNodeTypeStringByType(Node::NodeType type)
{
    switch (type) {
        case NodeType_Generic:
            return "Generic";
        case NodeType_FillRate:
            return "FillRate";
        default:
            return "Undefined";
    }
}

void Node::setWeightValue(int weight)
{
    weightValue = std::min(Node::MAX_WEIGHT, std::max(weight, Node::MIN_WEIGHT));
}

int Node::getWeightValue()
{
    return weightValue;
}

int Node::getWidth() const
{
    return width;
}

int Node::getHeight() const
{
    return height;
}

float Node::getWindowRatio() const
{
    return width / (float)height;
}

Node::RunningState Node::run()
{
    RunningState result = RunningState_Failed;
    frameNum = 0;
    perfwindow = PerfWindow::get();

#ifdef USE_GLES
    /* For GLES, whether the MSAA is open is determined when the window is created.
     * So to test msaa function, need to re-create window with MSAA enabled */
    if (strcmp(getNodeName().data(), "Msaa") == 0) {
        perfwindow->destory();

        perfwindow->setWindowMsaa(true);
        perfwindow->create();
    }
#endif

    textRender = new TextRender();
    auto init = textRender->init("../media/fonts/NotoSansMono.ttf", 14);

    if (!init) {
        std::cout << "init text render failed, bad text shader?\n";
        return result;
    }

    textRender->onResize(width, height);

    startTime = glfwGetTime();
    lastTime = startTime;

    float privTime = startTime;
    perfwindow->setRenderNode(this);

    if (!startup())
        return result;

    result = RunningState_Success;

    float difDelay;
    float startTimeVar = startTime;
    bool firstFps = true;

    char fpsStr[30] = {0};

    do {
        double current = glfwGetTime();
        float dif = current - privTime;
        render(current, dif);

        if (firstFps) {
            firstFps = false;
            difDelay = dif;
        }

        if (current - startTimeVar > 0.8) {
            startTimeVar = current;
            difDelay = dif;
        }

        sprintf(fpsStr, "fps:%.2f", 1.0 / difDelay);
        textRender->render(fpsStr);

        perfwindow->swapBuffer();

        frameNum++;
        privTime = current;
        lastTime = privTime - startTime;

        int error = glGetError();
        if (error != GL_NO_ERROR)
            result = RunningState_Failed;

        if (!perfwindow->processInput()) {
            result = RunningState_Abort;
            break;
        }
    } while (lastTime < totalTime);

    delete textRender;
    textRender = nullptr;

    shutdown();
    endTime = glfwGetTime();
    averageFps = frameNum / (endTime - startTime);

#ifdef USE_GLES
    /* For GLES, we re-create window with MSAA on.
     * When testcase Msaa is complete, close the MSAA window return to common window */
    if (strcmp(getNodeName().data(), "Msaa") == 0) {
        perfwindow->destory();

        perfwindow->setWindowMsaa(false);
        perfwindow->create();
    }
#endif

    return result;
}

float Node::getAverageFps()
{
    return averageFps;
}

std::string Node::getNodeName() const
{
    return nodeName;
}

bool Node::startup()
{
    return true;
}

void Node::render(double currentTime, double difTime)
{
}

void Node::shutdown()
{
}

void Node::onResized(int width, int height)
{
    if (height == 0)
        height = 1;

    this->width = width;
    this->height = height;
    glViewport(0, 0, width, height);

    if (textRender)
        textRender->onResize(width, height);
}

int Node::isExtensionSupported(const char *extName)
{
    GLint numExtensions;
    GLint i;

    glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);

    for (i = 0; i < numExtensions; i++) {
        const GLubyte *e = glGetStringi(GL_EXTENSIONS, i);
        if (!strcmp((const char *)e, extName)) {
            return 1;
        }
    }

    return 0;
}
